package com.kvest.sqlitetest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.kvest.sqlitetest.datastorage.sqlitestorage.MultithreadingSQLiteManager;
import com.kvest.sqlitetest.datastorage.sqlitestorage.MultithreadingTestHelper;
import com.kvest.sqlitetest.datastorage.sqlitestorage.TestHelper;

public class MainActivity extends Activity {
    private TestHelper testHelper;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        testHelper = new TestHelper(getApplicationContext());
    }

    public void onPrintDBClick(View view) {
        //Print count
        testHelper.printCountAll();

        //print data
        testHelper.printAll();
    }

    public void onFillDBClick(View view){
        testHelper.fill();
    }

    public void onClearDBtClick(View view) {
        testHelper.clear();
    }

    public void onSpeedTestClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                testHelper.speedTest();
            }
        }).start();
    }

    public void onDistinctTestClick(View view) {
        testHelper.distinctTest();
    }

    public void onLimitTestClick(View view) {
        testHelper.limitTest();
    }

    public void onGroupByTestClick(View view) {
        testHelper.groupByTest();
    }

    public void onHavingTestClick(View view) {
        testHelper.havingTest();
    }

    public void onCaseTestClick(View view) {
        testHelper.stringCaseTest();
    }

    public void onLikeTestClick(View view) {
        testHelper.likeCaseTest();
    }

    public void onUniqueNotNullTestClick(View view) {
        testHelper.uniqueNotNullTest();
    }

    public void onNestedTestClick(View view) {
        testHelper.nestedTest();
    }

    public void onIndexTestClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                testHelper.indexTest();
            }
        }).start();
    }

    public void onJoinTestClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                testHelper.joinTest();
            }
        }).start();
    }

    public void onForeignKeyTestClick(View view) {
        testHelper.foreignKeyTest();
    }

    public void onTriggerTestClick(View view) {
        testHelper.triggerTest();
    }

    public void onOpenNotOpenSpeedTestClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                testHelper.openNotOpenSpeedTest();
            }
        }).start();
    }

    public void onTransactionTestClick(View view) {
        testHelper.transactionTest();
    }

    public void onInsertOrUpdateTestClick(View view) {
        testHelper.insertOrUpdateTest();
    }

    public void onMultithreadingTestClick(View view) {
        //При разработке многопоточного доступа - хорошо все продумать. НАверно лучше держать открытое соединение и давать доступ
        //через synchronized методы. Возможно поэксперементировать прагмами и чистым SQL для реализации паралелльности

        //Более подходящяя БД для многопоточки
        new Thread(new MultiDBWriter(7000, 7)).start();
        new Thread(new MultiDBWriter(8000, 10)).start();

        new Thread(new MultiDBReader(0)).start();
        new Thread(new MultiDBReader(7)).start();
        new Thread(new MultiDBReader(9)).start();
        new Thread(new MultiDBReader(12)).start();
        new Thread(new MultiDBReader(17)).start();
        new Thread(new MultiDBReader(21)).start();
        new Thread(new MultiDBReader(24)).start();
        final MultithreadingTestHelper db = new MultithreadingTestHelper(getApplicationContext());
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; ++i) {
                    db.printCountWithTag("firm " + 107);
                }
                Log.d("KVEST_TAG", "thread finished");
            }
        }).start();
        //NOTE!!! Если вызвать этот код - падает. Т.е. для записи несколько БД лучше не открывать. Для чтения - вроде проблем нет
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                for (int i = 0; i < 100; ++i) {
//                    db.fillProduct(9000, 5);
//                }
//                Log.d("KVEST_TAG", "thread finished");
//            }
//        }).start();

        //Bad implementation!!!!
        //Эти три потока нормально бегают параллельно, если  внутри в DBWriter при вызове fillFirm используется
        //транзакции. Если нет - ошибка.
//        new Thread(new DBWriter(testHelper, 0, 10)).start();
//        new Thread(new DBWriter(testHelper, 10, 10)).start();
//        new Thread(new DBWriter(testHelper, 20, 10)).start();

        //Эти потоки вместе не могут работать вообще.
        //new Thread(new DBReader(testHelper, 0)).start();
//        new Thread(new DBReader(testHelper, 7)).start();
//        new Thread(new DBReader(testHelper, 9)).start();
//        new Thread(new DBReader(testHelper, 12)).start();
//        new Thread(new DBReader(testHelper, 17)).start();
//        new Thread(new DBReader(testHelper, 21)).start();
//        new Thread(new DBReader(testHelper, 24)).start();
    }

    public static class DBWriter implements Runnable {
        private TestHelper testHelper;
        private int offset;
        private int count;

        public DBWriter(TestHelper testHelper, int offset, int count) {
            this.testHelper = testHelper;
            this.count = count;
            this.offset = offset;
        }

        @Override
        public void run() {
            for (int i = 0; i < 100; ++i) {
                testHelper.fillFirm(offset, count);
                Log.d("KVEST_TAG", "!!!!!");
            }
            Log.d("KVEST_TAG", "thread finished");
        }
    }

    public static class DBReader implements Runnable {
        private TestHelper testHelper;
        private int id;

        public DBReader(TestHelper testHelper, int id) {
            this.testHelper = testHelper;
            this.id = id;
        }

        @Override
        public void run() {
            for (int i = 0; i < 1000; ++i) {
                testHelper.getFirm("firm " + id);
            }
            Log.d("KVEST_TAG", "thread finished");
        }
    }

    public static class MultiDBWriter implements Runnable {
        private int offset;
        private int count;

        public MultiDBWriter(int offset, int count) {
            this.count = count;
            this.offset = offset;
        }

        @Override
        public void run() {
            for (int i = 0; i < 100; ++i) {
                MultithreadingSQLiteManager.getInstance().fillProduct(offset, count);
            }
            Log.d("KVEST_TAG", "thread finished");
        }
    }

    public static class MultiDBReader implements Runnable {
        private int id;

        public MultiDBReader(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            for (int i = 0; i < 1000; ++i) {
                MultithreadingSQLiteManager.getInstance().printCountWithTag(Integer.toString(id));
            }
            Log.d("KVEST_TAG", "thread finished " + id);
        }
    }

    public void onLimitVsOffsetClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("KVEST_TAG", "onLimitVsOffsetClick");
                testHelper.limitVsOffsetTest();
            }
        }).start();
    }

    public void onFillMultithreadingDBClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("KVEST_TAG", "onFillMultithreadingDBClick");
                MultithreadingSQLiteManager db = MultithreadingSQLiteManager.getInstance();
                db.clear();
                db.fill();
                db.printAll();
            }
        }).start();
    }
}
